package org.hepeng.fabric.gateway.event.spring;

import org.hepeng.fabric.gateway.event.CCEventDefinition;
import org.hepeng.fabric.gateway.event.CCEventListener;
import org.hepeng.fabric.gateway.event.CCEventListenerMethod;
import org.hepeng.fabric.gateway.event.CCEventListenerRegistry;
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.MethodIntrospector;
import org.springframework.core.annotation.AnnotatedElementUtils;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.Set;

/**
 * @author he peng
 * @date 2022/3/30
 */
public class CCEventListenerMethodProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

        Class<?> type = AopProxyUtils.ultimateTargetClass(bean);

        Map<Method, CCEventListener> selectMethods = MethodIntrospector.selectMethods(type,
                (MethodIntrospector.MetadataLookup<CCEventListener>) method ->
                        AnnotatedElementUtils.findMergedAnnotation(method, CCEventListener.class));

        Set<Method> methods = selectMethods.keySet();

        for (Map.Entry<Method, CCEventListener> entry : selectMethods.entrySet()) {
            CCEventListener ccEventListener = entry.getValue();

            for (String event : ccEventListener.events()) {

                CCEventListenerRegistry.add(
                        new CCEventDefinition(ccEventListener.chaincode().trim() , ccEventListener.channel().trim() , event.trim()) ,
                        new CCEventListenerMethod(bean , methods));
            }
        }

        return bean;
    }
}
